 
/**
 * @file    app_voice.c
 * @author  Azolla (1228449928@qq.com)
 * @brief   led contorl PWM
 * @version 0.1
 * @date    2022-12-06
 * 
 * @copyright Copyright (c) 2022
 * */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "driver/uart.h"
#include "freertos/queue.h"
#include "esp_log.h"
#include "sdkconfig.h"
#include "driver/gpio.h"

#include "app_voice.h"

#define TAG "app_voice"

// Note: Some pins on target chip cannot be assigned for UART communication.
// Please refer to documentation for selected board and target to configure pins using Kconfig.
#define UART_PIN_TXD       (37)
#define UART_PIN_RXD       (36)
#define UART_PIN_RTS       (UART_PIN_NO_CHANGE)
#define UART_PIN_CTS       (UART_PIN_NO_CHANGE)
 
static const uart_port_t uart_port = UART_NUM_2;
static const uart_mode_t uart_mode = UART_MODE_UART;
 
#define UART_BUFF_SIZE     (127)
 
// Timeout threshold for UART = number of symbols (~10 tics) with unchanged state on receive pin
#define UART_READ_TOUT      (3) // 3.5T * 8 = 28 ticks, TOUT=3 -> ~24..33 ticks

#define UART_BUSY_PIN      (26)

static QueueHandle_t write_queue = NULL;      // 队列
// if (xQueueReceive(write_queue, &info, 2000) == pdTRUE) { 
// xQueueSend(write_queue, &info, (TickType_t)100);  // 发送队列数据
//  write_queue = xQueueCreate(3, sizeof(mqtt_data_t));
//================================================================================================= 
//================================================================================================= 
 
void voice_sendto_bytes(const uint8_t *data, uint8_t len)
{
    if (uart_write_bytes(uart_port, data, len) != len) {
        // add your code to handle sending failure here
    } else {
        ESP_ERROR_CHECK( uart_wait_tx_done(uart_port, 20) );  
    }
}
 
static void uart_driver_init(void)
{
    uart_config_t uart_config = {
        .baud_rate = 9600,
        .data_bits = UART_DATA_8_BITS,
        .parity    = UART_PARITY_DISABLE,
        .stop_bits = UART_STOP_BITS_1,
        .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
        .source_clk= UART_SCLK_APB,
    };
 
    // Install UART driver (we don't need an event queue here)
    // In this example we don't even use a buffer for sending data.
    ESP_ERROR_CHECK(uart_driver_install(uart_port, UART_BUFF_SIZE * 2, 0, 0, NULL, 0));

    // Configure UART parameters
    ESP_ERROR_CHECK(uart_param_config(uart_port, &uart_config));
 
    // Set UART pins as per KConfig settings
    ESP_ERROR_CHECK(uart_set_pin(uart_port, UART_PIN_TXD, UART_PIN_RXD, UART_PIN_RTS, UART_PIN_CTS));

    // Set RS485 half duplex mode
    ESP_ERROR_CHECK(uart_set_mode(uart_port, uart_mode));

    // Set read timeout of UART TOUT feature
    ESP_ERROR_CHECK(uart_set_rx_timeout(uart_port, UART_READ_TOUT));
}

void voice_write_cmd(uint8_t cmd, uint8_t datah, uint8_t datal);
 
static void uart_read_task(void *arg)
{
    // Allocate buffers for UART
    #define UART_BUFF_SZIE     16
    uint8_t *data = (uint8_t *) malloc(UART_BUFF_SZIE);
    if (data == NULL) vTaskDelete(NULL);

    // ESP_LOGI(TAG, "UART[%d] start recieve loop.\r\n", uart_port);

    // vTaskDelay(1000);
    voice_set_vol(6);  // 设置音量！
    voice_set_vol(6);  // 设置音量！
  
    voice_data_t frame;
 
    while ( true ) {
 
        if (xQueueReceive(write_queue, &frame, portMAX_DELAY) == pdTRUE) { // portMAX_DELAY
            uart_write_bytes(uart_port, frame.data, frame.len);
            // esp_log_buffer_hex("voice_write", frame.data, frame.len);
        }  
 
        // Read data from UART
        int len = uart_read_bytes(uart_port, data, UART_BUFF_SZIE, 2000);
        if (len > 0) {
            // esp_log_buffer_hex("voice_read", data, len);
        }  
        vTaskDelay(200);  // 固定每次播放结束都延时个200ms
    }
    vTaskDelete(NULL);
}

//============================================================================================
//============================================================================================
// KT404C 语音芯片
 
void voice_write_cmd(uint8_t cmd, uint8_t datah, uint8_t datal)
{
    voice_data_t frame;
    frame.data[0] = 0x7E;
    frame.data[1] = 0xFF;
    frame.data[2] = 0x06;
    frame.data[3] = cmd;
    frame.data[4] = 0x00;    // 0x00: 不需要反馈
    frame.data[5] = datah;  
    frame.data[6] = datal;   
    frame.data[7] = 0xEF;   
    frame.len = 8;
    xQueueSend(write_queue, &frame, (TickType_t)100);  // 发送队列数据
}

void voice_set_vol(uint8_t vol)
{
    voice_write_cmd(0x06, 0x00, vol); // 设置音量 
}

bool voice_is_busy(void)
{
    return gpio_get_level(UART_BUSY_PIN);
}

// 0x0F 指定文件夹文件名播放
void app_voice_speech(uint8_t voice)
{
    // voice_write_cmd(0x0F, dir, voice);  // dir: 文件夹01; voice: 曲目
    voice_write_cmd(0x0F, 0x01, voice);  // dir: 文件夹01; voice: 曲目
}
 
// uart_port_t uart_port = UART_NUM_1;
void app_voice_init(void)
{
    // gpio_set_direction(UART_BUSY_PIN, GPIO_MODE_INPUT);
    // gpio_pullup_en(UART_BUSY_PIN);

    write_queue = xQueueCreate(3, sizeof(voice_data_t));
    uart_driver_init();
    xTaskCreatePinnedToCore(uart_read_task, "voice_task", 3 * 1024, NULL, 5, NULL, APP_CPU_NUM);   
#if 0  // Test.
    uint8_t voice_file = 1;
    while (1) {
        vTaskDelay(3000);
        app_voice_speech(voice_file++);
        if (voice_file > 13) voice_file = 1;
    }
#endif    
}
